package intermediately

import (
	"bytes"
	"github.com/hyperledger/fabric-protos-go/common"
	"github.com/hyperledger/fabric/common/tools/protolator"
	"github.com/pkg/errors"
)

func EncodeProto(input *common.Block) ([]byte, error) {

	var w = new(bytes.Buffer)
	if err := protolator.DeepMarshalJSON(w, input); err != nil {
		return nil, errors.Wrapf(err, "error encoding output")
	}
	return w.Bytes(), nil

}

func EncodeCommonProto(input interface{}) ([]byte, error) {
	var w = new(bytes.Buffer)
	if err := protolator.DeepMarshalJSON(w, input.(*common.Block)); err != nil {
		return nil, errors.Wrapf(err, "error encoding output")
	}
	return w.Bytes(), nil
}

// ---------------------------------------------------------------------------------------------------------------------
//var jsons = jsoniter.ConfigCompatibleWithStandardLibrary
//
////func Marshal(v interface{}) ([]byte, error) {
////	return json.Marshal(v)
////}
////
////func Unmarshal(data []byte, v interface{}) error {
////	return json.Unmarshal(data, v)
////}
//
//type FabricBlock struct {
//	Number            uint64              `json:"number"`
//	CurrentBlockHash  string              `json:"currentBlockHash"`
//	PreviousBlockHash string              `json:"previousBlockHash"`
//	Transactions      []FabricTransaction `json:"transactions"`
//}
//
//type FabricTransaction struct {
//	No        int64                     `json:"no"`
//	Status    string                    `json:"status"`
//	Txid      string                    `json:"txid"`
//	Channel   string                    `json:"channel"`
//	Type      string                    `json:"type"`
//	Subject   string                    `json:"subject"`
//	Config    string                    `json:"config"`
//	Timestamp int64                     `json:"timestamp"`
//	Actions   []FabricTransactionAction `json:"actions"`
//}
//
//type FabricTransactionAction struct {
//	Endorsers []string                       `json:"endorsers"`
//	RWSet     []FabricTransactionActionRWSet `json:"rwSet"`
//}
//
//type FabricTransactionActionRWSet struct {
//	Cc   string   `json:"cc"`
//	RSet []string `json:"rSet"`
//	WSet []string `json:"wSet"`
//}
//
//
//type RsetE struct {
//	Key string `json:"key"`
//	Version *kvrwset.Version `json:"version"`
//}
//
//type WsetE struct {
//	Key string `json:"key"`
//	IsDelete bool `json:"is_delete"`
//	Value string `json:"value"`
//}
//
//
//
//
////func decorate(block *common.Block ) *common.Block{
////	if block == nil {
////		return nil
////	}
////	cmBlock := new(common.Block)
////	cmBlock.Data = &common.BlockData{
////		Data:block.Data.Data,
////	}
////	cmBlock.Header= &common.BlockHeader{
////		Number: block.Header.Number,
////		PreviousHash: block.Header.PreviousHash,
////		DataHash: block.Header.DataHash,
////	}
////	cmBlock.Metadata =&common.BlockMetadata{
////		Metadata: block.Metadata.Metadata,
////	}
////	return cmBlock
////}
//
//func decodeSerializedIdentity(creator []byte) (string, error) {
//	certStart := bytes.Index(creator, []byte("-----BEGIN"))
//	if certStart == -1 {
//		return "", fmt.Errorf("No certificate found")
//	}
//	certText := creator[certStart:]
//	//bl, _ := pem.Decode(certText)
//	//if bl == nil {
//	//	return "", fmt.Errorf("Could not decode the PEM structure")
//	//}
//	//cert, err := x509.ParseCertificate(bl.Bytes)
//	//if err != nil {
//	//	return "", err
//	//}
//	//fmt.Println(cert)
//	// uname := cert.Subject.CommonName
//
//	return string(certText), nil
//}
//
//func parseBlock(block *common.Block) (*FabricBlock, error) {
//	if block == nil {
//		return nil, nil
//	}
//	var err error
//	faBlock := new(FabricBlock)
//	trans := make([]FabricTransaction, 0)
//	// Handle header
//	faBlock.Number = block.GetHeader().Number
//	faBlock.CurrentBlockHash = hex.EncodeToString(block.GetHeader().DataHash)
//	faBlock.PreviousBlockHash = hex.EncodeToString(block.GetHeader().PreviousHash)
//	// Handle transaction
//	var tranNo int64 = -1
//	txsFilter := util.TxValidationFlags(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
//	if len(txsFilter) == 0 {
//		txsFilter = util.NewTxValidationFlags(len(block.Data.Data))
//		block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = txsFilter
//	}
//
//	for _, envBytes := range block.Data.Data {
//		tran := FabricTransaction{}
//		tranNo++
//		tran.No = tranNo
//		if txsFilter.IsInvalid(int(tranNo)) {
//			tran.Status = "INVALID"
//			continue
//		} else {
//			tran.Status = "VALID"
//		}
//		// GetEnvelopeFromBlock
//		var env = &common.Envelope{}
//		if err = proto.Unmarshal(envBytes, env); err != nil {
//			return nil, errors.New("error unmarshaling Envelope --> " + err.Error())
//		}
//		var payload = &common.Payload{}
//		// GetPayload
//		if err := proto.Unmarshal(env.Payload, payload); err != nil {
//			return nil, errors.New("error unmarshaling Payload-->" + err.Error())
//		}
//		// UnmarshalChannelHeader
//		var chdr = &common.ChannelHeader{}
//		if err := proto.Unmarshal(payload.Header.ChannelHeader, chdr); err != nil {
//			return nil, err
//		}
//		tran.Txid = chdr.TxId
//		tran.Channel = chdr.ChannelId
//		tran.Timestamp = chdr.Timestamp.GetSeconds()
//		var shdr = &common.SignatureHeader{}
//		if err := proto.Unmarshal(payload.Header.SignatureHeader, shdr); err != nil {
//			return nil, errors.New("error unmarshaling SignatureHeader -->" + err.Error())
//		}
//		var subject string
//		subject, err = decodeSerializedIdentity(shdr.Creator)
//		if err != nil {
//			return nil, err
//		}
//		tran.Subject = subject
//		if common.HeaderType(chdr.Type) == common.HeaderType_CONFIG {
//			tran.Type = "CONFIG"
//			conf, err := parseConfig(payload)
//			if err != nil {
//				return nil, err
//			}
//			tran.Config = string(conf)
//		} else if common.HeaderType(chdr.Type) == common.HeaderType_ENDORSER_TRANSACTION {
//			tran.Type = "ENDORSER_TRANSACTION"
//			actions, err := parseEndorserTransaction(payload)
//			if err != nil {
//				return nil, err
//			}
//			tran.Actions = actions
//		} else {
//			tran.Type = "UNKNOWN"
//		}
//
//		trans = append(trans, tran)
//	}
//	faBlock.Transactions = trans
//	return faBlock, nil
//}
//
//func parseEndorserTransaction(payload *common.Payload) ([]FabricTransactionAction, error) {
//	var err error
//	//  GetTransaction
//	var tx = &peer.Transaction{}
//	if err := proto.Unmarshal(payload.Data, tx); err != nil {
//		return nil, err
//	}
//	actions := make([]FabricTransactionAction, len(tx.Actions))
//	for i, action := range tx.Actions {
//		act := FabricTransactionAction{}
//
//		var ca *peer.ChaincodeAction
//		var capayload *peer.ChaincodeActionPayload
//		capayload, ca, err = GetPayloads(action)
//		if err != nil {
//			fmt.Println(err.Error(), 2)
//		}
//
//		if err != nil {
//			return nil, err
//		}
//		endorsers := make([]string, len(capayload.Action.Endorsements))
//		for j, endorser := range capayload.Action.Endorsements {
//			var subject string
//			subject, err = decodeSerializedIdentity(endorser.Endorser)
//			if err != nil {
//				return nil, err
//			}
//			endorsers[j] = subject
//		}
//		act.Endorsers = endorsers
//		//-------------------------------------
//
//		//-------------------------------------
//		txRWSet := &rwsetutil.TxRwSet{}
//		err = txRWSet.FromProtoBytes(ca.Results)
//		if err != nil {
//			return nil, err
//		}
//
//		rwSets := make([]FabricTransactionActionRWSet, 0)
//		for _, nsRWSet := range txRWSet.NsRwSets {
//			ns := nsRWSet.NameSpace
//			if ns != "lscc" { // skip system chaincode
//				rwSet := FabricTransactionActionRWSet{}
//				rwSet.Cc = ns
//				rset := make([]string, len(nsRWSet.KvRwSet.Reads))
//
//				for i, kvRead := range nsRWSet.KvRwSet.Reads {
//					restT := &RsetE{
//						Key:     kvRead.Key,
//						Version: kvRead.Version,
//					}
//
//					jsonByte, _ := json.Marshal(restT)
//					//rset[i] = fmt.Sprintf("key=%v,version=%v", kvRead.Key, kvRead.Version)
//					rset[i] = string(jsonByte)
//				}
//				rwSet.RSet = rset
//
//				wset := make([]string, len(nsRWSet.KvRwSet.Writes))
//				for i, kvWrite := range nsRWSet.KvRwSet.Writes {
//					wsetET :=&WsetE{
//						Key:       kvWrite.Key,
//						IsDelete: kvWrite.IsDelete,
//						Value:    string(kvWrite.Value),
//					}
//					jsonByer,_ := json.Marshal(wsetET)
//		//			fmt.Println(  fmt.Sprintf("key=%v,isDelete=%v,value=%v", kvWrite.Key, kvWrite.IsDelete, string(kvWrite.Value)))
//					wset[i] = string(jsonByer)
//				//	wset[i] = fmt.Sprintf("key=%v,isDelete=%v,value=%v", kvWrite.Key, kvWrite.IsDelete, string(kvWrite.Value))
//				}
//				rwSet.WSet = wset
//				rwSets = append(rwSets, rwSet)
//			}
//		}
//		act.RWSet = rwSets
//		actions[i] = act
//	}
//	return actions, nil
//}
//
//
//func parseConfig(payload *common.Payload) ([]byte, error) {
//	var err error
//	// UnmarshalConfigEnvelope
//	var configEnvelope = &common.ConfigEnvelope{}
//	if err := proto.Unmarshal(payload.Data, configEnvelope); err != nil {
//		return nil, err
//	}
//	config := configEnvelope.Config
//	conf, err := jsons.Marshal(config)
//	if err != nil {
//		return nil, err
//	}
//	return conf, nil
//}
//
//func GetPayloads(txActions *peer.TransactionAction) (*peer.ChaincodeActionPayload, *peer.ChaincodeAction, error) {
//	// GetChaincodeActionPayload
//	ccPayload := &peer.ChaincodeActionPayload{}
//	err := proto.Unmarshal(txActions.Payload, ccPayload)
//	if err != nil {
//		return nil, nil, err
//	}
//	if ccPayload.Action == nil || ccPayload.Action.ProposalResponsePayload == nil {
//		return nil, nil, errors.New("no payload in ChaincodeActionPayload")
//	}
//	//GetProposalResponsePayload
//	pRespPayload := &peer.ProposalResponsePayload{}
//	err = proto.Unmarshal(ccPayload.Action.ProposalResponsePayload, pRespPayload)
//	if err != nil {
//		return nil, nil, errors.New("error unmarshaling ProposalResponsePayload --> " + err.Error())
//	}
//	if pRespPayload.Extension == nil {
//		return nil, nil, errors.New("response payload is missing extension")
//	}
//
//	// GetChaincodeAction
//	respPayload := &peer.ChaincodeAction{}
//	err = proto.Unmarshal(pRespPayload.Extension, respPayload)
//	if err != nil {
//		return ccPayload, nil, err
//	}
//	return ccPayload, respPayload, nil
//}
